package com.bestcem.xm.user.util.business.captcha;

import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.user.constant.CookieConstant;
import com.bestcem.xm.user.constant.UserCacheKeyConstant;
import com.bestcem.xm.user.util.business.CookieUtil;
import com.bestcem.xm.user.util.business.UserCacheUtil;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.UnsupportedEncodingException;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 图形验证码工具类
 *
 * @author wangyunyun <yunyun.wang@idiaoyan.com>
 * @version v1.0
 * @date 2022/6/6 19:00
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Component
public class CaptchaUtil {

    @Autowired
    private UserCacheUtil userCacheUtil;

    private static final Random rand = new Random();

    /**
     * 创建验证码图片对象
     *
     * @param captcha
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/6/7 10:44
     */
    public void createCaptcha(Captcha captcha) throws UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder();
        // 创建空白图片
        BufferedImage image = new BufferedImage(captcha.getWidth(), captcha.getHeight(), BufferedImage.TYPE_INT_RGB);
        // 获取图片画笔
        Graphics2D graphic = image.createGraphics();
        // 设置抗锯齿
        graphic.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        // 绘制矩形背景
        graphic.fillRect(0, 0, captcha.getWidth(), captcha.getHeight());
        // 画随机字符
        Random ran = rand;
        // 设置背景颜色
        graphic.setBackground(captcha.getBackgroundColor());

        // 计算每个字符占的宽度，这里预留一个字符的位置用于左右边距
        int codeWidth = captcha.getWidth() / (captcha.getSize() + 1);
        // 字符所处的y轴的坐标
        int y = captcha.getHeight() * 3 / 4;

        for (int i = 0; i < captcha.getSize(); i++) {
            // 设置随机颜色
            graphic.setColor(getRandomColor());
            // 设置字体
            Font font = captcha.getFont();

            if (Boolean.TRUE.equals(captcha.getTilt())) {
                // 随机一个倾斜的角度 -30到30度之间
                int theta = ran.nextInt(captcha.getThetaRange());
                // 随机一个倾斜方向 左或者右
                theta = (ran.nextBoolean()) ? theta : -theta;
                AffineTransform affineTransform = new AffineTransform();
                affineTransform.rotate(Math.toRadians(theta), 0, 0);
                font = font.deriveFont(affineTransform);
            }
            // 设置字体大小
            graphic.setFont(font);

            // 计算当前字符绘制的X轴坐标
            int x = (i * codeWidth) + (codeWidth / 2);

            // 得到字符文本
            String code = captcha.randomCode(ran);
            // 画字符
            graphic.drawString(code, x, y);

            // 记录字符
            sb.append(code);
        }

        // 画干扰线
        for (int i = 0; i < captcha.getLines(); i++) {
            // 设置随机颜色
            graphic.setColor(getRandomColor());
            // 随机画线
            graphic.drawLine(ran.nextInt(captcha.getWidth()), ran.nextInt(captcha.getHeight()), ran.nextInt(captcha.getWidth()), ran.nextInt(captcha.getHeight()));
        }

        // 设置验证码以及对应的验证码图片
        captcha.setVscode(sb.toString());
        captcha.setImage(image);
        // 设置缓存
        userCacheUtil.setEx(userCacheUtil.buildKey(UserCacheKeyConstant.LOGIN_IMG_CAPTCHA, captcha.getKey()), captcha.getVscode(), 6000, TimeUnit.SECONDS);
    }

    /**
     * 校验图形验证码
     *
     * @param captchaKey  验证码key
     * @param captchaCode 图形验证码内容
     * @return com.bestcem.xm.util.ServiceResult<java.lang.Void>
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/08 14:07
     */
    public ServiceResult<Void> checkImgCaptcha(String captchaKey, String captchaCode) {
        return ServiceResult.success();
        // 校验图形验证码
        /*if (StringUtils.isBlank(captchaCode)) {
            return ServiceResult.fail(ValidationErrorCodeEnum.CAPTCHA_ERROR, "请输入图形验证码");
        }
        String cacheCode = userCacheUtil.get(UserCacheKeyConstant.LOGIN_IMG_CAPTCHA, captchaKey);
        if (StringUtils.isBlank(cacheCode) || !cacheCode.equalsIgnoreCase(captchaCode)) {
            return ServiceResult.fail(ValidationErrorCodeEnum.CAPTCHA_ERROR, "图形验证码错误,请重新输入");
        }
        return ServiceResult.success();*/
    }

    /**
     * 随机取色
     *
     * @return Color
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/6/6 19:03
     */
    private Color getRandomColor() {
        Random ran = rand;
        return new Color(ran.nextInt(256), ran.nextInt(256), ran.nextInt(256));
    }

    /**
     * 从RequestContextHolder中获取HttpServletRequest
     *
     * @return HttpServletRequest
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @date 2022/8/9 11:05
     */
    public HttpServletRequest getRequest() {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        return requestAttributes.getRequest();
    }

    /**
     * 设置登录失败次数 +1
     *
     * @param response
     * @param username
     * @param ipAddress
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @version v1.0
     * @date 2022/3/6 14:30
     */
    public void setLoginCaptcha(HttpServletResponse response, String username, String ipAddress) {
        // 添加缓存
        String loginCaptchaKey = userCacheUtil.buildKey(UserCacheKeyConstant.LOGIN_CAPTCHA_COUNT, username, ipAddress);
        Long captchaCount = userCacheUtil.incrByKey(loginCaptchaKey);
        userCacheUtil.expire(loginCaptchaKey, 3600);
        // 添加cookie
        CookieUtil.setCookie(getRequest(), response, CookieConstant.LOGIN_CAPTCHA_COUNT, String.valueOf(captchaCount));
    }

    /**
     * 清除登录失败次数
     *
     * @param response
     * @param username
     * @param ipAddress
     * @author wangyunyun <yunyun.wang@idiaoyan.com>
     * @version v1.0
     * @date 2022/3/6 14:30
     */
    public void clearLoginCaptcha(HttpServletResponse response, String username, String ipAddress) {
        // 删除缓存
        userCacheUtil.delete(UserCacheKeyConstant.LOGIN_CAPTCHA_COUNT, username, ipAddress);
        // 删除cookie
        CookieUtil.deleteCookie(getRequest(), response, CookieConstant.LOGIN_CAPTCHA_COUNT);
    }
}
